#include "common.h"
#include <signal.h>

/* ****************************************************************** */
/* begin/end/clean entries from other components */

extern void memory_begin(void);
extern void memory_dump(void);
extern void memory_end(void);

static void __begin(void)
{
	memory_begin();
}

static void __dump(void)
{
	memory_dump();
}

static void __end(void)
{
	memory_end();
}

/* ****************************************************************** */

t_libc_func libc_funcs[] = {
	{ LIBC_MALLOC, "malloc", NULL },
	{ LIBC_CALLOC, "calloc", NULL },
	{ LIBC_REALLOC, "realloc", NULL },
	{ LIBC_FREE, "free", NULL },
	{ LIBC_MMAP, "mmap", NULL },
	{ LIBC_MREMAP, "mremap", NULL },
	{ LIBC_MUNMAP, "munmap", NULL },
	{ LIBC_POSIX_MEMALIGN, "posix_memalign", NULL },
	{ LIBC_MEMALIGN, "memalign", NULL },
};

/* get address of libc functions */
int init_libc_handles(void)
{
	int i, ret;
	
	ret = 0;
	for (i = 0; i < LIBC_FUNCS_MAX; i++) {
		libc_funcs[i].handle = dlsym(RTLD_NEXT, libc_funcs[i].name);
		if (libc_funcs[i].handle == NULL) {
			ret = -1;
			perr("dlsym %s failed!\n", libc_funcs[i].name);
		}
	}

	return ret;
}

/* override SIGTSTP */
void sig_tstp_handle(int signum)
{
	pdbg("enter signal handle: %d\n", signum);

	__dump();
}

/* override SIGINT */
void sig_int_handle(int signum)
{
	pdbg("enter signal handle: %d\n", signum);

	__dump();
	__end();
	exit(1);
}

/* override SIGTERM */
void sig_term_handle(int signum)
{
	pdbg("enter signal handle: %d\n", signum);

	__dump();
	__end();
	exit(1);
}

/* libanotherc startup entry */
static void __attribute__ ((constructor)) common_init(void)
{
	plog("#### common init done!\n");

	if (init_libc_handles()) {
		perr("init_libc_handlers() failed!\n");
		exit(1);
	}
	
	signal(SIGTSTP, sig_tstp_handle);
	signal(SIGINT, sig_int_handle);
	signal(SIGTERM, sig_term_handle);

	__begin();
}

/* libanotherc exit entry */
static void __attribute__ ((destructor)) common_fini(void)
{
	plog("#### common fini done!\n");

	__dump();
	__end();
}
